﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using MSProject = Microsoft.Office.Interop.MSProject;
using Office = Microsoft.Office.Core;
using System.Runtime.InteropServices;
using System.Collections;
using System.Text.RegularExpressions;

namespace MindManagerLiteImport
{
    public partial class ThisAddIn
    {
        private const string STR_BTN_CAPTION = "Import From MindManager";
        Microsoft.Office.Core.CommandBar standardBar = null;
        Microsoft.Office.Core.CommandBarButton importBtn = null;

        private void ThisAddIn_Startup(object sender, System.EventArgs e)
        {
            // Set up a custom button on the "Standard" commandbar.
            try
            {
                standardBar = Application.CommandBars["Standard"];
            }
            catch (Exception)
            {
                // Access names its main toolbar Database.
                standardBar = Application.CommandBars["Database"];
            }

            // In case the button was not deleted, use the exiting one.
            try
            {
                importBtn = (Microsoft.Office.Core.CommandBarButton)standardBar.Controls[STR_BTN_CAPTION];
            }
            catch (Exception)
            {
                object omissing = System.Reflection.Missing.Value;
                importBtn = (Microsoft.Office.Core.CommandBarButton)standardBar.Controls.Add(1, omissing, omissing, omissing, omissing);
                importBtn.Caption = STR_BTN_CAPTION;
                importBtn.Style = Microsoft.Office.Core.MsoButtonStyle.msoButtonCaption;
            }

            // The following items are optional, but recommended. 
            //The Tag property lets you quickly find the control 
            //and helps MSO keep track of it when more than
            //one application window is visible. The property is required
            //by some Office applications and should be provided.
            //importBtn.Tag = "My Custom Button";

            // The OnAction property is optional but recommended. 
            //It should be set to the ProgID of the add-in, so that if
            //the add-in is not loaded when a user presses the button,
            //MSO loads the add-in automatically and then raises
            //the Click event for the add-in to handle. 
            //importBtn.OnAction = "!<MyCOMAddin.Connect>";

            importBtn.Visible = true;
            importBtn.Click += new Microsoft.Office.Core._CommandBarButtonEvents_ClickEventHandler(this.ImportButton_Click);

        }

        private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
        {
            object omissing = System.Reflection.Missing.Value;
            importBtn.Delete(omissing);
            importBtn = null;
        }

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InternalStartup()
        {
            this.Startup += new System.EventHandler(ThisAddIn_Startup);
            this.Shutdown += new System.EventHandler(ThisAddIn_Shutdown);
        }

        Dictionary<string, Microsoft.Office.Interop.MSProject.Task> taskMappings = null;
        Dictionary<string, int> taskMappingNum = null;
        List<MindManager.Relationship> dependentTasks = null;

        private void ImportButton_Click(Microsoft.Office.Core.CommandBarButton cmdBarbutton, ref bool cancel)
        {
            MindManager.ApplicationClass app = new MindManager.ApplicationClass();
            MindManager.Topic mainTopic = app.ActiveDocument.CentralTopic;
            taskMappings = new Dictionary<string, Microsoft.Office.Interop.MSProject.Task>();
            taskMappingNum = new Dictionary<string, int>();
            dependentTasks = new List<MindManager.Relationship>();

            int count = 1;
            int level = 1;

            Microsoft.Office.Interop.MSProject.Task task = Application.ActiveProject.Tasks.Add(mainTopic.Text, count);
            count++;
            AddTopics(mainTopic, task, ref count, ref level, true);

            //process dependent tasks
            foreach (MindManager.Relationship r in dependentTasks)
            {
                Microsoft.Office.Interop.MSProject.Task task2;
                string taskNum;
                try
                {
                    task2 = taskMappings[r.ConnectedObject2.Guid];
                    taskNum = taskMappingNum[r.ConnectedObject1.Guid] + "";
                    task2.Predecessors = (!string.IsNullOrEmpty(task2.Predecessors) ? task2.Predecessors + "," : "") + taskNum;
                }
                catch { }
            }

            Marshal.ReleaseComObject(app);
        }

        private void AddTopics(MindManager.Topic topic, Microsoft.Office.Interop.MSProject.Task task, ref int count, ref int level, bool shouldIndent)
        {
            bool hasIndented = false;
            foreach (MindManager.Topic subtopic in topic.AllSubTopics)
            {
                //if (!subtopic.IsVisible)
                //    continue;

                if (task == null)
                    task = Application.ActiveProject.Tasks.Add(subtopic.Text, count);
                else
                {
                    task = task.OutlineChildren.Add(subtopic.Text, count);

                    //map the current task information to work out the relationships later on
                    int curCount = count;
                    taskMappings.Add(subtopic.Guid, task);
                    taskMappingNum.Add(subtopic.Guid, curCount);
                    if (subtopic.AllRelationships.Count > 0)
                    {
                        foreach (MindManager.Relationship r in subtopic.AllRelationships)
                        {
                            dependentTasks.Add(r);
                        }
                    }

                    if (!hasIndented && shouldIndent)
                    {
                        hasIndented = true;
                        task.OutlineIndent();
                    }

                    while (level > subtopic.Level)
                    {
                        task.OutlineOutdent();
                        level--;
                    }
                }

                task.Notes = subtopic.Notes.Text;
                task.Text1 = subtopic.Guid;
                //subtopic.Task.DurationInHours;
                Match m = Regex.Match(task.Name, @"(\[([0-9]+)(\w)\])");
                if (m.Success)
                {
                    task.Duration = m.Result("$2$3");
                    task.Name = task.Name.Replace(m.Result("$1"), "");
                }

                //finished processing this task, increment count
                count++;

                if (subtopic.AllSubTopics != null && subtopic.AllSubTopics.Count > 0)
                {
                    level++;
                    AddTopics(subtopic, task, ref count, ref level, true);
                }
            }
        }
    }
}
